import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { Upload, message, Modal } from 'antd';
import ReactCrop from 'react-image-crop';
import request from '@/utils/request';
import 'react-image-crop/dist/ReactCrop.css';
import styles from './style.less';

function getBase64(img, callback) {
  const reader = new FileReader();
  reader.addEventListener('load', () => callback(reader.result));
  reader.readAsDataURL(img);
}

export default class extends PureComponent {
  static propTypes = {
    onUpload: PropTypes.func
  }

  static defaultProps = {
    onUpload: () => {}
  }

  state = {
    src: null,
    crop: {
      aspect: 2,
      width: 50,
      height: 25,
      x: 0,
      y: 0,
    },
    visible: false,
    fileList: [],
    uploading: false,
    oss: {},
  };

  componentDidMount() {
    this.NProgress = window.NProgress;
  }

  onImageLoaded = (image, pixelCrop) => {
    this.imageRef = image;

    // Make the library regenerate aspect crops if loading new images.
    const { crop } = this.state;

    if (crop.aspect && crop.height && crop.width) {
      this.setState({
        crop: { ...crop, height: null },
      });
    } else {
      this.makeClientCrop(crop, pixelCrop);
    }
  };

  onCropComplete = (crop, pixelCrop) => {
    this.makeClientCrop(crop, pixelCrop);
  };

  onCropChange = crop => {
    this.setState({ crop });
  };

  getCroppedImg(image, pixelCrop, fileName) {
    const canvas = document.createElement('canvas');
    canvas.width = pixelCrop.width;
    canvas.height = pixelCrop.height;
    const ctx = canvas.getContext('2d');

    ctx.drawImage(
      image,
      pixelCrop.x,
      pixelCrop.y,
      pixelCrop.width,
      pixelCrop.height,
      0,
      0,
      pixelCrop.width,
      pixelCrop.height,
    );

    this.setState({
      oss: {
        x: pixelCrop.x,
        y: pixelCrop.y,
        w: pixelCrop.width,
        h: pixelCrop.height,
      }
    })

    return new Promise((resolve, reject) => {
      canvas.toBlob(blob => {
        blob.name = fileName;
        window.URL.revokeObjectURL(this.fileUrl);
        this.fileUrl = window.URL.createObjectURL(blob);
        resolve(this.fileUrl);
      }, 'image/jpeg');
      reject();
    });
  }

  beforeUpload = (file) => {
    getBase64(file, imageUrl => this.setState(state => ({
      fileList: [...state.fileList, file],
      src: imageUrl,
      loading: false,
      visible: true
    })));
    return false;
  }

  onUpload = () => {
    const { oss, fileList } = this.state;
    const { onUpload } = this.props;
    const formData = new FormData();
    formData.append('oss', `w_${(oss.w).toFixed(0)},h_${(oss.h).toFixed(0)},x_${(oss.x).toFixed(0)},y_${(oss.y).toFixed(0)}`);
    fileList.forEach((file) => {
      formData.append('files[]', file);
    });

    this.setState({
      uploading: true,
    });
    this.NProgress.inc(0.5);
    this.NProgress.set(0.5);
    this.NProgress.start();

    request(`${API_PREFIX}/uploads`, {
        method: 'POST',
        body: formData,
      })
      .then(res => {
        onUpload(res);
        this.setState({
          fileList: [],
          uploading: false,
          visible: false,
        });
        message.success('裁剪上传成功～');
        this.NProgress.done();
      })
      .catch(e => {
        onUpload(e);
        this.setState({
          uploading: false,
        });
        message.error('图片裁剪上传失败～');
      });
  }

  handleCancel = () => {
    this.setState(state => ({
      ...state,
      visible: false
    }))
  }

  async makeClientCrop(crop, pixelCrop) {
    if (this.imageRef && crop.width && crop.height) {
      const croppedImageUrl = await this.getCroppedImg(
        this.imageRef,
        pixelCrop,
        'newFile.jpeg',
      );
      this.setState({ croppedImageUrl });
    }
  }

  render() {
    const { children } = this.props;
    const { visible, crop, croppedImageUrl, src, uploading, oss } = this.state;

    return (
      <div>
        <Upload
          showUploadList={false}
          beforeUpload={this.beforeUpload}
          {...this.props}
        >
          {
            children
          }
        </Upload>
        <Modal
          title="图像裁剪"
          visible={visible}
          onOk={this.onUpload}
          onCancel={this.handleCancel}
          okButtonProps={{loading: uploading, disabled: !src}}
          okText={uploading ? '上传中' : ''}
          width={500}
          bodyStyle={{position: 'relative', padding: 0, fontSize: 0}}
        >
          {src && (
            <ReactCrop
              src={src}
              crop={crop}
              onImageLoaded={this.onImageLoaded}
              onComplete={this.onCropComplete}
              onChange={this.onCropChange}
              className={styles.reactCropSource}
            />
          )}
          {
            croppedImageUrl 
            &&
            <section className={styles.reactCropTarget}>
              <img alt="Crop" src={croppedImageUrl} />
              <section className={styles.des}>宽：{oss.w}PX 高：{oss.h}PX</section>
            </section>
          }
        </Modal>
      </div>
    );
  }
}